// Panel.h

#ifndef __PANEL_H
#define __PANEL_H


#include "AppState.h"
#include "PanelMessages.h"
#include "FileManager/FileSystem/Directory.h"

#include "Common/FileSystem/SysIconUtils.h"

#include <vector>

const int kParentFolderID = 100;
const int kPluginMenuStartID = 1000;
const int kToolbarStartID = 2000;

void PanelCopyItems();

class CPanel;

class CMyListView: public CWindowImpl<CMyListView, CListViewCtrl>
{
public:
	BOOL PreTranslateMessage(MSG* pMsg)
	{
		pMsg;
		return FALSE;
	}
	DECLARE_WND_SUPERCLASS(NULL, CListViewCtrl::GetWndClassName())
	BEGIN_MSG_MAP(CMyListView)
	MESSAGE_HANDLER(WM_CHAR, OnChar)
	MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar)
	//MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) //This one is causing problem with keyboard navigation
	//MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) //This one is causing problem with showing selection
	END_MSG_MAP()
	CPanel* _panel;
	LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL &bHandled);
	LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL & /*bHandled*/);
	LRESULT OnSysChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL & /*bHandled*/);
	LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL & /*bHandled*/);
};

class CMyComboBoxEdit: public CWindowImpl<CMyComboBoxEdit, CEdit>
{
public:
	BEGIN_MSG_MAP(CMyComboBoxEdit)
	MESSAGE_HANDLER(WM_CHAR, OnChar)
	MESSAGE_HANDLER(WM_SYSKEYDOWN, OnSysKeyDown)
	MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
	END_MSG_MAP()

	LRESULT OnSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL & /*bHandled*/);
	LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL & /*bHandled*/);
	LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL & /*bHandled*/);
	CPanel* _panel;

};

struct CSelectedState
{
	int FocusedItem;
	CString FocusedName;
	bool SelectFocused;
	CStringVector SelectedNames;
	CSelectedState(): FocusedItem(-1), SelectFocused(false) {}
};

#ifdef UNDER_CE
#define MY_NMLISTVIEW_NMITEMACTIVATE NMLISTVIEW
#else
#define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE
#endif

class CMainWnd;

class CPanel: public CWindowImpl<CPanel>
{
	typedef CWindowImpl<CPanel> baseClass;
public:
	DECLARE_WND_CLASS(_T("7-Zip::Panel"))

	BEGIN_MSG_MAP(CPanel)
	MSG_WM_CREATE(OnCreate)
	//MSG_WM_NOTIFY(OnNotify)
	MSG_WM_DESTROY(OnDestroy)
	MSG_WM_SIZE(OnSize)
	MESSAGE_HANDLER(WM_NOTIFY, OnNotifyHandler)
	MESSAGE_HANDLER(kShiftSelectMessage, OnShiftSelectMessage)
	MESSAGE_HANDLER(kReLoadMessage, OnRefreshListCtrl)
	MESSAGE_HANDLER(kSetFocusToListView, OnSetFocusToListview)
	MESSAGE_HANDLER(kOpenItemChanged, OnOpenItemChanged)
	MESSAGE_HANDLER(kRefreshStatusBar, OnRefreshStatusBar)
	MESSAGE_HANDLER(kRefreshHeaderComboBox, OnRefreshCombobox)
	MSG_WM_TIMER(OnTimer)
	MSG_WM_CONTEXTMENU(OnContextMenu)
	COMMAND_ID_HANDLER(kParentFolderID, OnParentFolder)
	COMMAND_ID_HANDLER(_comboBoxID, OnComboBox)
	END_MSG_MAP()

public:
	int OnCreate(LPCREATESTRUCT lpCreateStruct);
	void OnDestroy();
	void OnSize(UINT nType, CSize size);
	void OnContextMenu(CWindow wnd, CPoint point);
	void OnTimer(UINT_PTR nIDEvent);

	LRESULT OnShiftSelectMessage(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL & /*bHandled*/);
	LRESULT OnRefreshListCtrl(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL & /*bHandled*/)
	{
		RefreshListCtrl(_selectedState);
		return 0;
	}

	LRESULT OnSetFocusToListview(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL & /*bHandled*/)
	{
		_listView.SetFocus();
		return 0;
	}

	LRESULT OnOpenItemChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL & /*bHandled*/);
	LRESULT OnRefreshStatusBar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL & /*bHandled*/);
	LRESULT OnRefreshCombobox(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL & /*bHandled*/)
	{
		LoadFullPathAndShow();
		return 0;
	}

	LRESULT OnNotifyHandler(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL &bHandled);

	LRESULT OnNotify(int /*idCtrl*/, LPNMHDR pnmh,  BOOL &bHandled);

	LRESULT OnParentFolder(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL & /*bHandled*/)
	{
		OpenParentFolder();
		return 0;
	}

	LRESULT OnComboBox(WORD wNotifyCode, WORD wID, HWND /*hWndCtl*/, BOOL & /*bHandled*/)
	{
		LRESULT result;
		OnComboBoxCommand(wNotifyCode, NULL, result);
		return result;
	}

	void OnRefreshStatusBar();


private:

	Common::FileSystem::CExtToIconMap _extToIconMap;
	UINT _baseID;
	int _comboBoxID;



	CAppState* _appState;

	void AddComboBoxItem(const CString &name, int iconIndex, int indent, bool addToList);

	bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result);

#ifndef UNDER_CE

	LRESULT OnNotifyComboBoxEnter(const CString &s);
	bool OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result);

#endif

	bool OnNotifyReBar(LPNMHDR lParam, LRESULT &result, BOOL &bHandled);
	bool OnNotifyComboBox(LPNMHDR lParam, LRESULT &result,  BOOL &bHandled);
	void OnItemChanged(NMLISTVIEW* item);
	void OnNotifyActivateItems();
	bool OnNotifyList(LPNMHDR lParam, LRESULT &result,  BOOL &bHandled);
	void OnDrag(LPNMLISTVIEW nmListView);
	bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result);
	BOOL OnBeginLabelEdit(LV_DISPINFOW* lpnmh);
	BOOL OnEndLabelEdit(LV_DISPINFOW* lpnmh);
	void OnColumnClick(LPNMLISTVIEW info);
	bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result);

public:
	HWND _mainWindow;
	CMainWnd* m_pApp;

	void SysIconsWereChanged()
	{
		_extToIconMap.Clear();
	}
	void DeleteItems(bool toRecycleBin);
	void CreateFolder();
	void CreateFile();

private:

	void ChangeWindowSize(CSize &size);

	HRESULT InitColumns();
	void InsertColumn(int index);

	void SetFocusedSelectedItem(int index, bool select);
	HRESULT RefreshListCtrl(const CString &focusedName, int focusedPos, bool selectFocused,
							const CStringVector &selectedNames);

	void OnArrowWithShift();

	void OnInsert();
public:
	void UpdateSelection();
	void SelectSpec(bool selectMode);
	void SelectByType(bool selectMode);
	void SelectAll(bool selectMode);
	void InvertSelection();
private:

	LRESULT SetItemText(LVITEMW &item);

public:
	CReBarCtrl _headerReBar;
	CToolBarCtrl _headerToolBar;
	CComboBoxEx    _headerComboBox;
	CStringVector ComboBoxPaths;
	CMyComboBoxEdit _comboBoxEdit;
	CMyListView _listView;
	CStatusBarCtrl _statusBar;
	bool _lastFocusedIsList;

	DWORD _exStyle;
	bool _showDots;
	bool _showRealFileIcons;
	bool _enableItemChangeNotify;
	bool _mySelectMode;
	typedef std::vector<bool> BoolVector;
	BoolVector _selectedStatusVector;

	CSelectedState _selectedState;

	UINT32 GetRealIndex(const LVITEMW &item) const
	{
		return (UINT32)item.lParam;
	}
	int GetRealItemIndex(int indexInListView) const
	{
		LPARAM param = _listView.GetItemData(indexInListView);
		return (int)param;
	}

	UINT32 _ListViewMode;
	int _xSize;

	bool _dontShowMode;

	CStringVector _fastFolders;

	FileManager::FileSystem::CDirectory m_directory;

	void GetSelectedNames(CStringVector &selectedNames);
	void SaveSelectedState(CSelectedState &s);
	HRESULT RefreshListCtrl(const CSelectedState &s);
	HRESULT RefreshListCtrlSaveFocused();

	////////////////////////
	// PanelFolderChange.cpp
	void OpenDrivesFolder();

	void SetBookmark(size_t index);
	void OpenBookmark(size_t index);

	void LoadFullPathAndShow();
	void FoldersHistory();
	void OpenFolder(int index);
	void OpenParentFolder();
	void SplitSelectedFiles();
	void CombineSelectedFiles();
	
	HWND Create(HWND mainWindow, HWND parentWindow, HWND statusWnd,
				UINT id,
				const CString &currentFolderPrefix,
				const CString &arcFormat,
				CMainWnd* app,
				CAppState* appState, bool &archiveIsOpened, bool &encrypted);
	void SetFocusToList();
	void SetFocusToLastRememberedItem();


	void ReadListViewInfo();
	void SaveListViewInfo();

	CPanel() :
		_exStyle(0),
		_showDots(false),
		_showRealFileIcons(false),
		_needSaveInfo(false),
		_startGroupSelect(0),
		_selectionIsDefined(false),
		_ListViewMode(3),
		_xSize(300),
		_mySelectMode(false),
		_enableItemChangeNotify(true),
		_dontShowMode(false)
	{}

	void SetExtendedStyle()
	{
		if (_listView != 0)
		{
			_listView.SetExtendedListViewStyle(_exStyle);
		}
	}


	bool _needSaveInfo;
	CString _typeIDString;
	CListViewInfo _listViewInfo;
	
	PROPID _sortID;
	bool _ascending;

	void Release();
	~CPanel();
	void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE* itemActivate);
	bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE* itemActivate, LRESULT &result,  BOOL &bHandled);
	void ShowColumnsContextMenu(CPoint point);

	void OnReload();

	CComPtr<IContextMenu> _sevenZipContextMenu;
	CComPtr<IContextMenu> _systemContextMenu;
	void CreateSystemMenu(HMENU menu,
						  const std::vector<UINT32> &operatedIndices,
						  CComPtr<IContextMenu> &systemContextMenu);
	void CreateSevenZipMenu(HMENU menu,
							const std::vector<UINT32> &operatedIndices,
							CComPtr<IContextMenu> &sevenZipContextMenu);
	void CreateFileMenu(HMENU menu,
						CComPtr<IContextMenu> &sevenZipContextMenu,
						CComPtr<IContextMenu> &systemContextMenu,
						bool programMenu);
	void CreateFileMenu(HMENU menu);
	bool InvokePluginCommand(int id);
	bool InvokePluginCommand(int id, IContextMenu* sevenZipContextMenu,
							 IContextMenu* systemContextMenu);

	void Properties();
	void EditCut();
	void EditCopy();
	void EditPaste();

	int _startGroupSelect;

	bool _selectionIsDefined;
	bool _selectMark;
	int _prevFocusedItem;


	void SortItemsWithPropID(PROPID propID);

	void GetSelectedItemsIndices(std::vector<UINT32> &indices) const;
	void GetOperatedItemIndices(std::vector<UINT32> &indices) const;
	void GetAllItemIndices(std::vector<UINT32> &indices) const;
	void GetOperatedIndicesSmart(std::vector<UINT32> &indices) const;
	void KillSelection();


	bool _processTimer;
	bool _processNotify;

	class CDisableTimerProcessing
	{
		bool _processTimerMem;
		bool _processNotifyMem;

		CPanel &_panel;
	public:

		CDisableTimerProcessing(CPanel &panel): _panel(panel)
		{
			Disable();
		}
		void Disable()
		{
			_processTimerMem = _panel._processTimer;
			_processNotifyMem = _panel._processNotify;
			_panel._processTimer = false;
			_panel._processNotify = false;
		}
		void Restore()
		{
			_panel._processTimer = _processTimerMem;
			_panel._processNotify = _processNotifyMem;
		}
		~CDisableTimerProcessing()
		{
			Restore();
		}
		CDisableTimerProcessing &operator=(const CDisableTimerProcessing &)
		{
			;
		}
	};

	HRESULT RefreshListCtrl();

	
	void OpenFocusedItemAsInternal();
	void OpenSelectedItems(bool internal);

	
	//OpenItemAsArchive
	
	void EditItem();
	
	void RenameFile();
	void ChangeComment();
	
	void SetListViewMode(UINT32 index);
	UINT32 GetListViewMode() const
	{
		return _ListViewMode;
	}
	PROPID GetSortID() const
	{
		return _sortID;
	}

	void ChangeFlatMode();
	bool GetFlatMode() const
	{
		return m_directory.GetFlatMode();
	}

	void RefreshStatusBar();

	void AddToArchive();

	void ExtractArchives();
	void TestArchives();

	void CopyFromNoAsk(const CStringVector &filePaths);
	void CopyFromAsk(const CStringVector &filePaths);

	void CopyItems(bool move, bool copyToSame);

	// empty folderPath means create new Archive to path of first fileName.
	void DropObject(IDataObject* dataObject, const CString &folderPath);

	// empty folderPath means create new Archive to path of first fileName.
	void CompressDropFiles(const CStringVector &fileNames, const CString &folderPath);

	void RefreshTitle(bool always = false);
	void RefreshTitleAlways()
	{
		RefreshTitle(true);
	}

};


#endif
